home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / FLTK-1.0.6 / fluid / code.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-05  |  8.4 KB  |  317 lines

  1. //
  2. // "$Id: code.cxx,v 1.9.2.2 1999/08/05 08:01:39 bill Exp $"
  3. //
  4. // Code output routines for the Fast Light Tool Kit (FLTK).
  5. //
  6. // Copyright 1998-1999 by Bill Spitzak and others.
  7. //
  8. // This library is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU Library General Public
  10. // License as published by the Free Software Foundation; either
  11. // version 2 of the License, or (at your option) any later version.
  12. //
  13. // This library is distributed in the hope that it will be useful,
  14. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. // Library General Public License for more details.
  17. //
  18. // You should have received a copy of the GNU Library General Public
  19. // License along with this library; if not, write to the Free Software
  20. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  21. // USA.
  22. //
  23. // Please report all bugs and problems to "fltk-bugs@easysw.com".
  24. //
  25.  
  26. #include <ctype.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <stdarg.h>
  31.  
  32. #include <FL/Fl.H>
  33. #include "Fl_Type.h"
  34. #include "alignment_panel.h"
  35.  
  36. static FILE *code_file;
  37. static FILE *header_file;
  38.  
  39. // return true if c can be in a C identifier.  I needed this so
  40. // it is not messed up by locale settings:
  41. int is_id(char c) {
  42.   return c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9' || c=='_';
  43. }
  44.  
  45. ////////////////////////////////////////////////////////////////
  46. // Generate unique but human-readable identifiers:
  47.  
  48. struct id {
  49.   char* text;
  50.   void* object;
  51.   id *left, *right;
  52.   id (const char* t, void* o) : text(strdup(t)), object(o) {left = right = 0;}
  53.   ~id();
  54. };
  55.  
  56. id::~id() {
  57.   delete left;
  58.   free((void *)text);
  59.   delete right;
  60. }
  61.  
  62. static id* id_root;
  63.  
  64. const char* unique_id(void* o, const char* type, const char* name, const char* label) {
  65.   char buffer[128];
  66.   char* q = buffer;
  67.   while (*type) *q++ = *type++;
  68.   *q++ = '_';
  69.   const char* n = name;
  70.   if (!n || !*n) n = label;
  71.   if (n && *n) {
  72.     while (!is_id(*n)) n++;
  73.     while (is_id(*n)) *q++ = *n++;
  74.   }
  75.   *q = 0;
  76.   // okay, search the tree and see if the name was already used:
  77.   id** p = &id_root;
  78.   int which = 0;
  79.   while (*p) {
  80.     int i = strcmp(buffer, (*p)->text);
  81.     if (!i) {
  82.       if ((*p)->object == o) return (*p)->text;
  83.       // already used, we need to pick a new name:
  84.       sprintf(q,"%x",++which);
  85.       p = &id_root;
  86.       continue;
  87.     }
  88.     else if (i < 0) p = &((*p)->left);
  89.     else p  = &((*p)->right);
  90.   }
  91.   *p = new id(buffer, o);
  92.   return (*p)->text;
  93. }
  94.  
  95. ////////////////////////////////////////////////////////////////
  96. // return current indentation:
  97.  
  98. static const char* spaces = "                ";
  99. int indentation;
  100. const char* indent() {
  101.   int i = indentation; if (i>16) i = 16;
  102.   return spaces+16-i;
  103. }
  104.  
  105. ////////////////////////////////////////////////////////////////
  106. // declarations/include files:
  107. // Each string generated by write_declare is written only once to
  108. // the header file.  This is done by keeping a binary tree of all
  109. // the calls so far and not printing it if it is in the tree.
  110.  
  111. struct included {
  112.   char *text;
  113.   included *left, *right;
  114.   included(const char *t) {
  115.     text = strdup(t);
  116.     left = right = 0;
  117.   }
  118.   ~included();
  119. };
  120.  
  121. included::~included() {
  122.   delete left;
  123.   free((void *)text);
  124.   delete right;
  125. }
  126. static included *included_root;
  127.  
  128. int write_declare(const char *format, ...) {
  129.   va_list args;
  130.   char buf[1024];
  131.   va_start(args, format);
  132.   vsprintf(buf, format, args);
  133.   va_end(args);
  134.   included **p = &included_root;
  135.   while (*p) {
  136.     int i = strcmp(buf,(*p)->text);
  137.     if (!i) return 0;
  138.     else if (i < 0) p = &((*p)->left);
  139.     else p  = &((*p)->right);
  140.   }
  141.   fprintf(header_file,"%s\n",buf);
  142.   *p = new included(buf);
  143.   return 1;
  144. }
  145.  
  146. ////////////////////////////////////////////////////////////////
  147.  
  148. // silly thing to prevent declaring unused variables:
  149. // When this symbol is on, all attempts to write code don't write
  150. // anything, but set a variable if it looks like the varaible "o" is used:
  151. int varused_test;
  152. int varused;
  153.  
  154. // write an array of C characters (adds a null):
  155. void write_cstring(const char *w, int length) {
  156.   if (varused_test) return;
  157.   const char *e = w+length;
  158.   int linelength = 1;
  159.   putc('\"', code_file);
  160.   for (; w < e;) {
  161.     int c = *w++;
  162.     switch (c) {
  163.     case '\b': c = 'b'; goto QUOTED;
  164.     case '\t': c = 't'; goto QUOTED;
  165.     case '\n': c = 'n'; goto QUOTED;
  166.     case '\f': c = 'f'; goto QUOTED;
  167.     case '\r': c = 'r'; goto QUOTED;
  168.     case '\"':
  169.     case '\'':
  170.     case '\\':
  171.     QUOTED:
  172.       if (linelength >= 77) {fputs("\\\n",code_file); linelength = 0;}
  173.       putc('\\', code_file);
  174.       putc(c, code_file);
  175.       linelength += 2;
  176.       break;
  177.     case '?': // prevent trigraphs by writing ?? as ?\?
  178.       if (*(w-2) == '?') goto QUOTED;
  179.       // else fall through:
  180.     default:
  181.       if (c >= ' ' && c < 127) {
  182.     // a legal ASCII character
  183.     if (linelength >= 78) {fputs("\\\n",code_file); linelength = 0;}
  184.     putc(c, code_file);
  185.     linelength++;
  186.     break;
  187.       }
  188.       // otherwise we must print it as an octal constant:
  189.       c &= 255;
  190.       if (c < 8) {
  191.     if (linelength >= 76) {fputs("\\\n",code_file); linelength = 0;}
  192.     fprintf(code_file, "\\%o",c);
  193.     linelength += 2;
  194.       } else if (c < 64) {
  195.     if (linelength >= 75) {fputs("\\\n",code_file); linelength = 0;}
  196.     fprintf(code_file, "\\%o",c);
  197.     linelength += 3;
  198.       } else {
  199.     if (linelength >= 74) {fputs("\\\n",code_file); linelength = 0;}
  200.     fprintf(code_file, "\\%o",c);
  201.     linelength += 4;
  202.       }
  203.       // We must not put more numbers after it, because some C compilers
  204.       // consume them as part of the quoted sequence.  Use string constant
  205.       // pasting to avoid this:
  206.       c = *w;
  207.       if (w < e && (c>='0'&&c<='9' || c>='a'&&c<='f' || c>='A'&&c<='F')) {
  208.     putc('\"', code_file); linelength++;
  209.     if (linelength >= 79) {fputs("\n",code_file); linelength = 0;}
  210.     putc('\"', code_file); linelength++;
  211.       }
  212.       break;
  213.     }
  214.   }
  215.   putc('\"', code_file);
  216. }
  217.  
  218. // write a C string, quoting characters if necessary:
  219. void write_cstring(const char *w) {write_cstring(w,strlen(w));}
  220.  
  221. void write_c(const char* format,...) {
  222.   if (varused_test) {varused = 1; return;}
  223.   va_list args;
  224.   va_start(args, format);
  225.   vfprintf(code_file, format, args);
  226.   va_end(args);
  227. }
  228.  
  229. void write_h(const char* format,...) {
  230.   if (varused_test) return;
  231.   va_list args;
  232.   va_start(args, format);
  233.   vfprintf(header_file, format, args);
  234.   va_end(args);
  235. }
  236.  
  237. #include <FL/filename.H>
  238. int write_number;
  239.  
  240. // recursively dump code, putting children between the two parts
  241. // of the parent code:
  242. static Fl_Type* write_code(Fl_Type* p) {
  243.   p->write_code1();
  244.   Fl_Type* q;
  245.   for (q = p->next; q && q->level > p->level;) q = write_code(q);
  246.   p->write_code2();
  247.   return q;
  248. }
  249.  
  250. int write_code(const char *s, const char *t) {
  251.   write_number++;
  252.   delete id_root; id_root = 0;
  253.   indentation = 0;
  254.   if (!s) code_file = stdout;
  255.   else {
  256.     FILE *f = fopen(s,"w");
  257.     if (!f) return 0;
  258.     code_file = f;
  259.   }
  260.   if (!t) header_file = stdout;
  261.   else {
  262.     FILE *f = fopen(t,"w");
  263.     if (!f) {fclose(code_file); return 0;}
  264.     header_file = f;
  265.   }
  266.   const char *hdr = "\
  267. // generated by Fast Light User Interface Designer (fluid) version %.2f\n\n";
  268.   fprintf(header_file, hdr, FL_VERSION);
  269.   fprintf(code_file, hdr, FL_VERSION);
  270.  
  271.   {char define_name[102];
  272.   const char* a = filename_name(t);
  273.   char* b = define_name;
  274.   if (!isalpha(*a)) {*b++ = '_';}
  275.   while (*a) {*b++ = isalnum(*a) ? *a : '_'; a++;}
  276.   *b = 0;
  277.   fprintf(header_file, "#ifndef %s\n", define_name);
  278.   fprintf(header_file, "#define %s\n", define_name);
  279.   }  
  280.  
  281.   write_declare("#include <FL/Fl.H>");
  282.  
  283.   if (t && include_H_from_C)
  284.     write_c("#include \"%s\"\n", filename_name(t));
  285.   for (Fl_Type* p = Fl_Type::first; p;) {
  286.     // write all static data for this & all children first
  287.     p->write_static();
  288.     for (Fl_Type* q = p->next; q && q->level > p->level; q = q->next)
  289.       q->write_static();
  290.     // then write the nested code:
  291.     p = write_code(p);
  292.   }
  293.  
  294.   delete included_root; included_root = 0;
  295.  
  296.   if (!s) return 1;
  297.   int x = fclose(code_file);
  298.   code_file = 0;
  299.   fprintf(header_file, "#endif\n");
  300.   int y = fclose(header_file);
  301.   header_file = 0;
  302.   return x >= 0 && y >= 0;
  303. }
  304.  
  305. ////////////////////////////////////////////////////////////////
  306.  
  307. void Fl_Type::write_static() {}
  308. void Fl_Type::write_code1() {
  309.   write_h("// Header for %s\n", title());
  310.   write_c("// Code for %s\n", title());
  311. }
  312. void Fl_Type::write_code2() {}
  313.  
  314. //
  315. // End of "$Id: code.cxx,v 1.9.2.2 1999/08/05 08:01:39 bill Exp $".
  316. //
  317.